/*
   file : where.c
   词法语法相关的函数 
   University of Jiangsu
   memoryDB      2010.6
 */


#include"shm_interface.h"
#include"where.h"

int IsNodeFull(Where_node *last_node)
{
	if(!last_node) return 1;
	if(last_node->R_atom) return 1;
	return 0;
}

int AddWhereNode(Where *w,Where_node *n, WhereTable *t)
{
	//printf("**********************AddWhereNode is called.\n");
	WhereTable* cur_p;
	if(!t)cur_p = w->Where_table_list;
	else cur_p = t;
	if(!cur_p->Where_node_list)
		w->Where_table_list->Where_node_list = n;
	else
		w->Where_table_list->last_node->Next_where_node  = n;
	w->Where_table_list->last_node = n;
	cur_p->Where_node_num++;
	return 1;
}

int AddWhereTable(Where *w,WhereTable *t)
{
	if(w->Where_table_list==NULL)
	{
		w->Where_table_list = t;
        strcpy(w->Where_table_list->name , t->name);

	}
	else
	{
		//多表·····；
	}
    return 1;
}

Field *Find_Recordfield(Record *r,char *field_name)
{
	Field* f = r->Field_list;
	if(!f)return NULL;
	for(;f;f = f->Next_Field)
	{
		if(!strcmp(f->Field_Name , field_name))
			return f;
	}
	return NULL;
}

int CmpFid_Fid(Field *lf,Field *rf,enum Cmp_opt opt)
{

	if(lf->date_type==rf->date_type&&lf->date_type==INTX)
	{   
		switch(opt)
		{
		case EQU:return (lf->Int_Val==rf->Int_Val)?1:0;
		case THAN:return (lf->Int_Val>rf->Int_Val)?1:0;
		case LESS:return (lf->Int_Val<rf->Int_Val)?1:0;
		default:return 0;
		}
	}

	if(lf->date_type==rf->date_type&&lf->date_type==DOUBLEX)
	{
		switch(opt)
		{
		case EQU:return (lf->Double_Val==rf->Double_Val)?1:0;
		case THAN:return (lf->Double_Val>rf->Double_Val)?1:0;
		case LESS:return (lf->Double_Val<rf->Double_Val)?1:0;
		default:return 0;

		}
	}

	if(lf->date_type==rf->date_type&&lf->date_type==STRINGX)
	{ 
                  
		switch(opt)
		{
		case EQU:return (strcmp(lf->Str_Val,rf->Str_Val)==0)?1:0;
		case THAN:return (strcmp(lf->Str_Val,rf->Str_Val)>0)?1:0;
		case LESS:return (strcmp(lf->Str_Val,rf->Str_Val)<0)?1:0;
		default: return 0;

		}
	}
      
	if((lf->date_type==STRINGX&&rf->date_type!=STRINGX)||\
		(rf->date_type==STRINGX&&lf->date_type!=STRINGX))return 0;
	if(lf->date_type==INTX&&rf->date_type==DOUBLEX)
	{
		switch(opt)
		{
		case EQU:return (lf->Int_Val==rf->Double_Val)?1:0;
		case THAN:return (lf->Int_Val>rf->Double_Val)?1:0;
		case LESS:return (lf->Int_Val<rf->Double_Val)?1:0;
		default:return 0;

		}
	}
	if(rf->date_type==INTX&&lf->date_type==DOUBLEX)
	{
		switch(opt)
		{
		case EQU:return (rf->Int_Val==lf->Double_Val)?1:0;
		case THAN:return (rf->Int_Val>lf->Double_Val)?1:0;
		case LESS:return (rf->Int_Val<lf->Double_Val)?1:0;
		default:return 0;
		}
	}
	return 0;

}

int DoWhere_Scan(char *Table_name,Where *w,Record *Cmp_field_list)
{
        if(!w->Where_table_list ||!w->Where_table_list->Where_node_list)
           return 1;
        else
        {
		int k=0;
		Where_node* cur_node = w->Where_table_list->Where_node_list;
		switch(w->where_type)
		{
		case ORX:
			{
				for(;k<w->Where_table_list->Where_node_num;k++,cur_node=cur_node->Next_where_node){
					if(cur_node->L_atom->Atom_type==FIELD){
						Field *f = Find_Recordfield(Cmp_field_list,cur_node->L_atom->Atom_field->Field_Name);
						cur_node->L_atom->Atom_field = f;

					}
					if(cur_node->R_atom->Atom_type==FIELD){
						Field *f = Find_Recordfield(Cmp_field_list,cur_node->R_atom->Atom_field->Field_Name);
						cur_node->R_atom->Atom_field = f;

					}
					if(CmpFid_Fid(cur_node->L_atom->Atom_field,cur_node->R_atom->Atom_field,cur_node->opt))
                                               return 1;
				}

			}
			break;
		case ANDX:
			{
				Row* r;
				for(k=0;k<w->Where_table_list->Where_node_num;k++,cur_node=cur_node->Next_where_node)
				{
					if(cur_node->L_atom->Atom_type==FIELD)
					{
						Field* f = Find_Recordfield(Cmp_field_list,cur_node->L_atom->Atom_field->Field_Name);
						cur_node->L_atom->Atom_field = f;

					}
					if(cur_node->R_atom->Atom_type==FIELD)
					{
						Field* f = Find_Recordfield(Cmp_field_list,cur_node->R_atom->Atom_field->Field_Name);
						cur_node->R_atom->Atom_field = f;

					}
                                    
					if(CmpFid_Fid(cur_node->L_atom->Atom_field,cur_node->R_atom->Atom_field,cur_node->opt))
                                            continue;

                                        else
                                            break;
				}
                                if(k==w->Where_table_list->Where_node_num)
                                   return 1;
                                else
                                   return 0;
                              
			}
			break;
		default:break;
		}
	}
	return 0;

}
void Get_Cmp_Field(Where *where,Record *Cmp_field_list)
{
        if(!where||!where->Where_table_list)
             return;
        Where_node *wt = where->Where_table_list->Where_node_list;
        //如果where条件不为空，则搜索where中比较所涉及的字段，保存在Cmp_field_list中
        if(wt)
	{
	  for(;wt;wt = wt->Next_where_node)
          {
		if(wt->R_atom->Atom_type==FIELD){
			Field *Fd = (Field*)malloc(sizeof(Field));
			Init_Field(Fd);
			strcpy(Fd->Field_Name , wt->R_atom->Atom_field->Field_Name);
			AddField_Record(Fd,Cmp_field_list);
		}
		if(wt->L_atom->Atom_type==FIELD){
			Field *Fd = (Field*)malloc(sizeof(Field));
			Init_Field(Fd);
			strcpy(Fd->Field_Name , wt->L_atom->Atom_field->Field_Name);
			AddField_Record(Fd,Cmp_field_list);
		}
	   }
        }
}

//执行Where语句的入口，返回一个行记录集合
int DoWhere(char *Table_name,Where *w,Record *Cmp_field_list)
{
	//执行where的方法，Scan方法；
	return DoWhere_Scan(Table_name,w,Cmp_field_list);
}
